﻿using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Common.Logging;
using Newtonsoft.Json;
using OutDbContext;
using Rmq.Center;
using User.Api.BizExtensions;
using User.Api.Helpers;
using User.Api.Helpers.WeixinPayV3.WxResult;
using User.Api.HttpClients;

namespace Out.TaskRunner.RmqWorkers
{
    public class OrderRefundingPickupFailedWorker : IWorker
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(OrderRefundingPickupFailedWorker));

        public void Start(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            using (var consumer = new OrderRefundingPickupFailedConsumer())
            {
                consumer.Subscribe((id, count, dt, msg, channel) =>
                {
                    if (msg.OrderType == OrderType.挂号订单)
                    {
                        return ProcessRegOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.门诊缴费订单)
                    {
                        return ProcessBillOrder(msg.OrderId, channel);
                    }
                    else if (msg.OrderType == OrderType.住院预缴金订单)
                    {
                        return ProcessInpatientPrepayOrder(msg.OrderId, channel);
                    }

                    return new ConsumedResult { Ack = true };
                });

                while (true)
                {
                    if (ct.IsCancellationRequested)
                    {
                        break;
                    }

                    Thread.Sleep(50);
                }
            }
        }

        private ConsumedResult ProcessRegOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.ApptOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                if (order.WxTransactionId == "0")
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                // 退款中
                order.OrderStatus = ApptOrderExtensions.OrderStatus.退款中.ToInt32();
                order.PayState = ApptOrderExtensions.PayState.退款中.ToInt32().ToString();
                order.RefundReason = order.OrderType == ApptOrderExtensions.OrderType.预约.ToInt32().ToString() 
                    ? "预约报到失败而退款" : "取号失败而退款";
                ctx.SaveChanges();

                var wxUser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);

                var refunFee = (order.SumFee.ToSingleOrDefault() * 100).ToInt32();
                var totalFee = (order.SumFee.ToSingleOrDefault() * 100).ToInt32();
                //检查用户是否有被设置成支付1分钱
                var isFromWxUserIdsForPayMin = false;
                if (order.WxUserId.HasValue)
                {
                    var refundWxUserIds = ConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
                    StringSplitOptions.RemoveEmptyEntries);
                    isFromWxUserIdsForPayMin = refundWxUserIds.Contains(order.WxUserId.ToStringOrDefault());
                }
                if (isFromWxUserIdsForPayMin)
                {
                    refunFee = (0.01 * 100).ToInt32();
                    totalFee = (0.01 * 100).ToInt32();
                }

                DoRefundResult refundResult;
                try
                {
                    refundResult = WeixinPayV3Helper.DoRefund("AP" + order.OrderNo, order.WxTransactionId,
                      "AP" + order.OrderNo, totalFee, refunFee);

                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
                //退款成功 4,10
                //退款处理中 8 9 11
                if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                    refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
                {
                    // 退款成功
                    order.OrderStatus = ApptOrderExtensions.OrderStatus.退款成功.ToInt32();
                    order.PayState = ApptOrderExtensions.PayState.已退款.ToInt32().ToString();
                    order.RefundTime = DateTime.Now;
                    order.WxRefundId = refundResult.RefundId;
                    ctx.SaveChanges();
                    
                    // RMQ 发送用户退费成功通知
                    var msgProducer = new UserMessageProducer();
                    msgProducer.Publish(new UserMessageMsg
                    {
                        Type = UserMessageType.挂号失败退费成功通知,
                        OrderId = order.Id
                    });

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                  .ToString(), "0", "RefundSucceed");

                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                //退款失败 3，5，6
                //转入代发 7
                if (refundResult.RefundStatus == 7 ||
                    refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
                {
                    // 退款失败
                    order.OrderStatus = ApptOrderExtensions.OrderStatus.退款失败.ToInt32();
                    order.PayState = ApptOrderExtensions.PayState.退款失败.ToInt32().ToString();
                    ctx.SaveChanges();

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "AP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                              .ToString(), "0", "RefundFailed");
                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 1，2：未确定，需要商户原退款单号重新发起
                if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
                {
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessBillOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.ClinRecipeOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 退款中
                order.OrderStatus = BillOrderExtensions.OrderStatus.退款中.ToInt32();
                order.PayState = BillOrderExtensions.PayState.退款中.ToInt32().ToString();
                ctx.SaveChanges();

                var wxUser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);

                var refunFee = (order.PayAmt.ToSingleOrDefault() * 100).ToInt32();
                var totalFee = (order.PayAmt.ToSingleOrDefault() * 100).ToInt32();
                //检查用户是否有被设置成支付1分钱
                var isFromWxUserIdsForPayMin = false;
                if (order.WxUserId.HasValue)
                {
                    var refundWxUserIds = ConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
                    StringSplitOptions.RemoveEmptyEntries);
                    isFromWxUserIdsForPayMin = refundWxUserIds.Contains(order.WxUserId.ToStringOrDefault());
                }
                if (isFromWxUserIdsForPayMin)
                {
                    refunFee = (0.01 * 100).ToInt32();
                    totalFee = (0.01 * 100).ToInt32();
                }

                DoRefundResult refundResult;
                try
                {
                    refundResult = WeixinPayV3Helper.DoRefund("BL" + order.OrderNo, order.WxTransactionId,
                      "BL" + order.OrderNo, totalFee, refunFee);

                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }

                // 1，2：未确定，需要商户原退款单号重新发起
                if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
                {
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
                //退款成功 4,10
                //退款处理中 8 9 11
                if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                    refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
                {
                    // 退款成功
                    order.OrderStatus = BillOrderExtensions.OrderStatus.退款成功.ToInt32();
                    order.PayState = BillOrderExtensions.PayState.已退款.ToInt32().ToString();
                    order.RefundTime = DateTime.Now;
                    order.WxRefundId = refundResult.RefundId;
                    ctx.SaveChanges();

                    // RMQ 发送用户退费成功通知
                    var messageProducer = new UserMessageProducer();
                    messageProducer.Publish(new UserMessageMsg
                    {
                        OrderId = order.Id,
                        Type = UserMessageType.缴费失败退款成功通知
                    });

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "BL" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                  .ToString(), "0", "RefundSucceed");

                    }
                }
                //退款失败 3，5，6
                //转入代发 7
                if (refundResult.RefundStatus == 7 ||
                    refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
                {
                    // 退款失败
                    order.OrderStatus = BillOrderExtensions.OrderStatus.退款失败.ToInt32();
                    order.PayState = BillOrderExtensions.PayState.退款失败.ToInt32().ToString();
                    ctx.SaveChanges();

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "BL" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                              .ToString(), "0", "RefundFailed");
                    }
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }

        private ConsumedResult ProcessInpatientPrepayOrder(int orderId, WrapperChannel channel)
        {
            using (var ctx = new FsssdqfybjyEntities())
            {
                var order = ctx.InpatientPrepayOrders.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 退款中
                order.OrderStatus = PrepayOrderExtensions.OrderStatus.退款中.ToInt32();
                order.PayState = PrepayOrderExtensions.PayState.退款中.ToInt32().ToString();
                ctx.SaveChanges();

                var wxUser = ctx.WxUsers.FirstOrDefault(x => x.Id == order.WxUserId);

                var refunFee = (order.PrepayMoney.ToSingleOrDefault() * 100).ToInt32();
                var totalFee = (order.PrepayMoney.ToSingleOrDefault() * 100).ToInt32();
                //检查用户是否有被设置成支付1分钱
                var isFromWxUserIdsForPayMin = false;
                if (order.WxUserId.HasValue)
                {
                    var refundWxUserIds = ConfigurationManager.AppSettings["UserIdsForPayMin"].Split(" , ",
                    StringSplitOptions.RemoveEmptyEntries);
                    isFromWxUserIdsForPayMin = refundWxUserIds.Contains(order.WxUserId.ToStringOrDefault());
                }
                if (isFromWxUserIdsForPayMin)
                {
                    refunFee = (0.01 * 100).ToInt32();
                    totalFee = (0.01 * 100).ToInt32();
                }

                DoRefundResult refundResult;
                try
                {
                    refundResult = WeixinPayV3Helper.DoRefund("IP" + order.OrderNo, order.WxTransactionId,
                      "IP" + order.OrderNo, totalFee, refunFee);
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("调用第三方支付退款Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
                //退款成功 4,10
                //退款处理中 8 9 11
                if (refundResult.RefundStatus == 4 || refundResult.RefundStatus == 10 ||
                    refundResult.RefundStatus == 8 || refundResult.RefundStatus == 9 || refundResult.RefundStatus == 11)
                {
                    // 退款成功
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.退款成功.ToInt32();
                    order.PayState = PrepayOrderExtensions.PayState.已退款.ToInt32().ToString();
                    order.RefundTime = DateTime.Now;
                    order.WxRefundId = refundResult.RefundId;
                    ctx.SaveChanges();

                    // RMQ 发送用户退费成功通知
                    var msgProducer = new UserMessageProducer();
                    msgProducer.Publish(new UserMessageMsg
                    {
                        Type = UserMessageType.住院预缴金失败退费成功通知,
                        OrderId = order.Id
                    });

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "IP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                                  .ToString(), "0", "RefundSucceed");

                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }
                //退款失败 3，5，6
                //转入代发 7
                if (refundResult.RefundStatus == 7 ||
                    refundResult.RefundStatus == 3 || refundResult.RefundStatus == 5 || refundResult.RefundStatus == 6)
                {
                    // 退款失败
                    order.OrderStatus = PrepayOrderExtensions.OrderStatus.退款失败.ToInt32();
                    order.PayState = PrepayOrderExtensions.PayState.退款失败.ToInt32().ToString();
                    ctx.SaveChanges();

                    if (wxUser != null)
                    {
                        WeixinPayV3Helper.DoDeliveryNotify(wxUser.OpenId, order.WxTransactionId,
                            "IP" + order.OrderNo, ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000)
                              .ToString(), "0", "RefundFailed");
                    }

                    return new ConsumedResult
                    {
                        Ack = true
                    };
                }

                // 1，2：未确定，需要商户原退款单号重新发起
                if (refundResult.RefundStatus == 1 || refundResult.RefundStatus == 2)
                {
                    return new ConsumedResult
                    {
                        Ack = false,
                        Delay = 1000
                    };
                }
            }

            return new ConsumedResult
            {
                Ack = true
            };
        }
    }
}